package com.cskaoyan.javase._2inner._1member._1basic;

/**
 * 要想弄清楚成员内部类的访问,要先明确两点:
 *      1.成员内部类和外围类是"好兄弟",它们之间的访问,
 *          统统不受权限限制,包括private
 *
 *      2.怎么理解成员内部类对象依赖于外围类对象而存在?
 *          成员内部类对象会持有外围类对象的引用
 *          所以要想得到成员内部类对象,必须肯定是在外围类对象的基础上创建的
 *          思考:
 *              a.在成员内部类的成员方法中,有几个对象呢?
 *              肯定存在this隐式传参,指向当前对象
 *              而且既然存在成员内部类对象,那么肯定存外围类对象
 *
 *              所以一共存在两个对象
 *              其一是当前成员内部类对象,用this关键字指向它
 *              其二是当前成员内部类的外围类对象,用"外围类类名.this"指向它
 *
 *              b.在成员内部类的静态成员方法中,有几个对象呢?(错,出题人错了,成员内部类当中没有静态成员方法)
 *
 *              c.在外围类的成员方法中,有几个对象呢?
 *              只有一个
 *              成员内部类对象需要依赖于外围类
 *              但反之不成立
 *              外围类的成员方法中,只有一个对象
 *              那就是外围类的自身对象,没有成员内部类对象
 *              既然不存在成员内部类对象,那么就需要创建它的对象,如何创建呢?
 *              外围类对象已经存在了,所以可以直接创建成员内部类对象,直接new对象.
 *
 *              d.在外围类的静态成员方法中,有几个对象呢?
 *              没有任何对象
 *              那么这里如果想要创建成员内部类对象,需要怎么做呢?
 *              不能直接new,需要先创建外围类对象
 *              然后在外围类对象的基础上创建成员内部类对象
 *
 * 成员内部类和外围类,外部类的访问特点
 * 成员内部类的访问特点，主要从以下几个角度研究：
 *      1.成员内部类内部访问外围类
 *          成员内部类当中只有成员方法,没有静态方法
 *          在成员内部类的成员方法中,如何访问外围类成员呢?
 *          已经存在外围类对象了,既然有对象,直接访问即可.
 *          但是当出现同名成员变量时,咋办呢?
 *          在成员内部类的成员方法中,存在外围类对象
 *          用"外围类类名.this"指向
 *          如果出现同名,用"外围类类名.this"区分即可.
 *
 *          当然如果出现全局常量同名,用类名点区分.
 *
 *      2.外围类访问成员内部类成员
 *          a.成员方法中访问
 *              因为不存成员内部类对象,所以需要创建它的对象
 *              直接new对象创建即可(因为已存在外围类对象)
 *              创建完对象后,该咋访问就咋访问
 *
 *          b.静态成员方法中访问
 *              因为不存成员内部类对象,所以需要创建它的对象
 *              但是创建成员内部类对象之前,需要先创建外围类对象,然后在外围类对象的基础上创建成员内部类对象
 *              如果出现同名,用不同的引用就是访问不同的成员.
 *
 *      3.外部类访问成员内部类成员
 *          首先外部类不是"好兄弟"了
 *          所以访问的全程都要受访问权限限制
 *          首先需要外围类权限
 *          其次需要成员内部类权限
 *          即便类的权限都有了,也需要有成员的权限.
 *
 *          思考:
 *          在外部类的成员方法和静态成员方法中,访问成员内部类成员,有区别吗?
 *          没有区别,反正都没有外围类对象,都需要先创建外围类对象
 *
 *          注意:
 *          既然都定义内部类了,内部类在外部能够访问的情况太少见了.仅做了解.
 *
 *      4.成员内部类访问外部类成员
 *          可以访问,需要创建对象
 *          需要受访问权限限制
 *          这种情况就更不多见了.
 *
 *
 *
 *
 * @since 17:13
 * @author wuguidong@cskaoyan.onaliyun.com
 */
// 外部类,其他类
public class Demo {
    public static void main(String[] args) {
        // 先创建外围类对象
        EnclosedClazz ec = new EnclosedClazz();
        // 在外围类对象的基础上创建成员内部类对象
        // 在外部类当中,写成员内部类的引用,需要指出外围类
        EnclosedClazz.InnerClazz ic = ec.new InnerClazz();

        // 上述二合一,链式调用
        EnclosedClazz.InnerClazz ic2 = new EnclosedClazz().new InnerClazz();

        System.out.println(ic.a);
        // System.out.println(ic.b);
    }

    public void test() {

    }
}

// 外围类
class EnclosedClazz {

    public void testEnclosed() {
        // 当前外围类对象
        System.out.println(this);
        // 直接创建成员内部类对象,因为外围类对象已存在
        InnerClazz ic = new InnerClazz();
        // 上述创建对象,实际上是利用了隐含的this传参
        // 如果把this写出来,表示在外围类对象的基础上创建成员内部类对象,如下所示:
        InnerClazz ic2 = this.new InnerClazz();
    }

    public static void testStaticEnclosed() {
        // 先创建外围类对象
        EnclosedClazz ec = new EnclosedClazz();
        // 在外围类对象的基础上创建成员内部类对象
        InnerClazz ic = ec.new InnerClazz();

        // 以上两步二合一,链式调用
        InnerClazz ic2 = new EnclosedClazz().new InnerClazz();
    }

    // 外围类的成员变量
    int a;
    private int b = 10;
    static int c = 20;
    static final int D = 30;

    // 成员内部类
    class InnerClazz {
        int a;
        // static int c = 20;
        private int b = 100;
        static final int D = 300;

        // 成员内部类的成员方法
        public void testInner(int b) {
            // 当前成员内部类对象
            System.out.println(this);
            // 当前成员内部类的外围类对象
            System.out.println(EnclosedClazz.this);
            System.out.println(a);
            System.out.println(EnclosedClazz.this.a);

            System.out.println(b);
            System.out.println(this.b);
            System.out.println(EnclosedClazz.this.b);

            System.out.println(EnclosedClazz.c);
            System.out.println(EnclosedClazz.D);

        }
    }
}